home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Prog / U-Z / Viewer.src.cpt / LineFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-12-30  |  4.5 KB  |  248 lines  |  [TEXT/KAHL]

  1. /* LineFile - low level file handler object
  2.     lines are clipped at 255 chars (including trailing \r)
  3.     messages:
  4.         LF_Open        Open a new file for reading, 
  5.                         return (LFile *) arg1
  6.                         return name in (char *) arg2
  7.         LF_GetLine    Return the line in (LFile *) arg1
  8.                         at offset arg3 from the one
  9.                         containing the char at arg2 (both long);
  10.                         line returned in arg4 (char *), linestart
  11.                         in arg5 (long *)
  12.         LF_Close    Close the file given by (LFile *) arg1
  13.                         Call this if you ever want to open it again!
  14.  
  15.     needs the external routine GenError(str1,str2,str3,str4); whose
  16.     arguments are Pascal strings
  17. */
  18.  
  19. #include <Quickdraw.h>
  20. #include <MemoryMgr.h>
  21. #include <StdFilePkg.h>
  22. #include <FileMgr.h>
  23. #include "LineFile.h"
  24.  
  25. #define NULL 0L
  26. #define EOF -1L
  27.  
  28. #define MaxLength    255
  29. #define DlglocV        70
  30. #define DlglocH        82
  31.  
  32. void doOpen();
  33. void doGetLine();
  34. void doClose();
  35.  
  36. void Pstrcpy( s1, s2 )
  37. unsigned char *s1, *s2;
  38. {
  39.     register unsigned char * p1 = s1, * p2 = s2;
  40.     register int i;
  41.     
  42.     for ( i = *p2; i >= 0; --i, ++p1, ++p2 )
  43.         *p1 = *p2;
  44. }
  45.  
  46. void LineFile( message, arg1, arg2, arg3, arg4, arg5 )
  47. int message;
  48. LFile *arg1;
  49. long arg2, arg3, arg4, arg5;
  50. {
  51.     switch ( message ) {
  52.         case LF_Open:
  53.             doOpen( arg1, arg2 ); break;
  54.         
  55.         case LF_GetLine:
  56.             doGetLine( arg1, arg2, arg3, arg4, arg5 ); break;
  57.         
  58.         case LF_Close:
  59.             doClose( arg1 ); break;
  60.         }
  61. }
  62.  
  63. static void doOpen( lfile, name )
  64. register LFile *lfile;
  65. char *name;
  66. {
  67.     SFReply        reply;
  68.     Point        where;
  69.     int            err;
  70.     char        errstr[256];
  71.     
  72.     where.v = DlglocV;
  73.     where.h = DlglocH;
  74.     
  75.     SFGetFile( where, "", NULL, 1, "TEXT", NULL, &reply );
  76.     
  77.     if ( reply.good ) {
  78.         if ( ( err = FSOpen( reply.fName, reply.vRefNum, &lfile->refnum ) )
  79.                 != noErr ) {
  80.             NumToString( (long) err, errstr );
  81.             GenError( "\pCould not open ", reply.fName,
  82.                       "\p, error ", errstr );
  83.             lfile->size = 0;
  84.             return;
  85.             }
  86.  
  87.         GetEOF( lfile->refnum, &lfile->size );
  88.         lfile->buf = NewHandle( L_BUFSIZE );
  89.         lfile->count = lfile->pos = 0;
  90.         lfile->start = 0L;
  91.         
  92.         Pstrcpy( name, reply.fName );
  93.         }
  94.  
  95.     else
  96.         lfile->size = 0;
  97.  
  98. }
  99.  
  100. int L_backc( f )        /* read char just before mark, back up */
  101. register LFile *f;
  102. {
  103.     long p, num_read = L_BUFSIZE;
  104.  
  105.     if ( f->pos > 0 )
  106.         return (*f->buf)[ --f->pos ];
  107.  
  108.     if ( f->start == 0L )
  109.         return EOF;
  110.     
  111.     p = f->start;
  112.     f->start -= L_BUFSIZE;
  113.     if ( f->start < 0L ) f->start = 0L;
  114.  
  115.     SetFPos( f->refnum, fsFromStart, f->start );
  116.     HLock( f->buf );
  117.     FSRead( f->refnum, &num_read, *f->buf );
  118.     HUnlock( f->buf );
  119.  
  120.     f->count = num_read;
  121.     f->pos = p - f->start;
  122.     if ( f->pos > num_read )
  123.         f->pos = num_read;
  124.  
  125.     if ( num_read == 0L )
  126.         return EOF;
  127.     else
  128.         return (*f->buf)[ --f->pos ];
  129. }
  130.  
  131. int L_getc( f )
  132. register LFile *f;
  133. {
  134.     long num_read = L_BUFSIZE;
  135.     
  136.     if ( f->pos < f->count )
  137.         return (*f->buf)[ f->pos++ ];
  138.  
  139.     f->start += f->count;
  140.     SetFPos( f->refnum, fsFromStart, f->start );
  141.     HLock( f->buf );
  142.     FSRead( f->refnum, &num_read, *f->buf );
  143.     HUnlock( f->buf );
  144.  
  145.     f->count = num_read;
  146.     f->pos = 0;
  147.  
  148.     if ( num_read == 0 )
  149.         return EOF;
  150.     else
  151.         return (*f->buf)[ f->pos++ ];
  152. }
  153.  
  154. void L_seek( f, charno )
  155. register LFile *f;
  156. long charno;
  157. {
  158.     f->start = charno;
  159.     f->count = f->pos = 0;
  160. }
  161.  
  162. int back_line( f )
  163. LFile *f;
  164. {
  165.     register int c;
  166.     
  167.     while ( ( c = L_backc( f ) ) != EOF &&
  168.              c != '\r' ) ;
  169.     
  170.     return c;
  171. }
  172.  
  173. int forward_line( f )
  174. LFile *f;
  175. {
  176.     register int c;
  177.     
  178.     while ( ( c = L_getc( f ) ) != EOF && c != '\r' ) ;
  179.     
  180.     return c;
  181. }
  182.  
  183. static void get_line( f, linestart,  newline )
  184. register LFile *f;
  185. long *linestart;
  186. register char newline[];
  187. {
  188.     register int c, i;
  189.     
  190.     *linestart = f->start + f->pos;
  191.  
  192.     for (    i = 0, c = L_getc( f );
  193.             i < MaxLength-1 && c != EOF && c != '\r';
  194.             ++i, c = L_getc( f ) )
  195.         newline[ i ] = c;
  196.  
  197.     newline[ i++ ] = '\r';
  198.     newline[ i ] = '\0';
  199. }
  200.  
  201. static void read_this_line( f, linestart, newline )
  202. LFile *f;
  203. long *linestart;
  204. char newline[];
  205. {
  206.     if ( back_line( f ) != EOF ) L_getc( f );    
  207.     get_line( f, linestart, newline );
  208. }
  209.  
  210. static void doGetLine( lfile, charno, offset, line, linestart )
  211. register LFile    *lfile;
  212. register long    charno, offset;
  213. long            *linestart;
  214. char            line[];
  215. {
  216.     register int  i;
  217.  
  218.     if ( charno > lfile->size || lfile->size <= 0 ) {
  219.         line[ 0 ] = '\0';
  220.         return;
  221.         }
  222.  
  223.     L_seek( lfile, charno );
  224.         
  225.     if ( offset > 0 )
  226.         for ( i = 0; i < offset; ++i )
  227.             if ( forward_line( lfile ) == EOF ) {
  228.                 line[ 0 ] = '\0';
  229.                 return;
  230.                 }
  231.  
  232.     if ( offset < 0 )
  233.         for ( i = 0; i > offset; --i )
  234.             if ( back_line( lfile ) == EOF ) {
  235.                 line[ 0 ] = '\0';
  236.                 return;
  237.                 }
  238.  
  239.     read_this_line( lfile, linestart, line );
  240. }
  241.  
  242. static void doClose( lfile )
  243. LFile *lfile;
  244. {
  245.     DisposHandle( lfile->buf );
  246.     FSClose( lfile->refnum );
  247. }
  248.